﻿@using BlazorMonaco
@using BlazorMonaco.Editor
@using BlazorMonaco.Languages
@using System.Text.Json.Nodes
@using FormBuilder.Factories
@using System.Text.Json
@using Json.Path
@inject IJSRuntime jsRuntime

<StandaloneCodeEditor @ref=editor OnDidInit="HandleOnDidInit" OnDidChangeModelContent="HandleOnEditorContentChanged" ConstructionOptions="EditorConstructionOptions" CssClass="jsonPathEditor" />
    
@code {
    private StandaloneCodeEditor editor;
    [Parameter] public string Value { get; set; }
    [Parameter] public JsonObject Json { get; set; }
    [Parameter] public WorkflowContext Context { get; set; }
    [Parameter] public JsonNode FakeData { get; set; }
    [Parameter] public string ParentPath { get; set; }
    [Parameter] public bool DisplayArray { get; set; }
    [Parameter] public EventCallback<string> ValueChanged { get; set; }
    [Inject] private IFakerDataServiceFactory fakerDataServiceFactory { get; set; }

    private async Task HandleOnEditorContentChanged()
    {
        Value = await editor.GetValue();
        await ValueChanged.InvokeAsync(Value);
        RefreshJsonPath();
    }

    private async Task HandleOnDidInit()
    {
        if(Value  != null) await editor.SetValue(Value);
        await editor.AddAction(new ActionDescriptor
        {
            Id = "submitInSingleMode",
            Label = "Submit in single mode",
            Keybindings = new int[] { (int)KeyCode.Enter },
            Run = (e) => { }
        });
    }

    private void RefreshJsonPath()
    {
        if (Context == null && FakeData == null) return;
        var allJsonPath = new List<string>();
        JsonNode jsonObj = FakeData;
        if(FakeData == null) 
        {
            var step = Context.GetCurrentFormRecord();
            var json = fakerDataServiceFactory.Generate(step.CorrelationId).Result;
            jsonObj = JsonObject.Parse(JsonSerializer.Serialize(json));
        }

        if(!string.IsNullOrWhiteSpace(ParentPath))
        {
            var path = JsonPath.Parse(ParentPath);
            var pathResult = path.Evaluate(jsonObj);
            var nodes = pathResult.Matches.Select(m => m.Value);
            if (!nodes.Any()) 
            {
                Context.FilteredJsonPath = string.IsNullOrWhiteSpace(Value) ? allJsonPath : allJsonPath.Where(p => p.StartsWith(Value)).ToList();
                return;
            }

            jsonObj = nodes.First(); 
        }

        foreach(var kvp in jsonObj.AsObject())
        {
            allJsonPath.AddRange(ExtractAllJsonPath($"$.{kvp.Key}", kvp.Value));
        }

        Context.FilteredJsonPath = string.IsNullOrWhiteSpace(Value) ? allJsonPath : allJsonPath.Where(p => p.StartsWith(Value)).ToList();
    }

    private List<string> ExtractAllJsonPath(string key, JsonNode node)
    {
        var result = new List<string>();
        var valueKind = node?.GetValueKind();
        if (
            (valueKind == JsonValueKind.Array && !DisplayArray) ||
            (valueKind != JsonValueKind.Array && DisplayArray)
        ) return result;
        if(valueKind == JsonValueKind.Array)
        {
            result.Add($"{key}[*]");
            return result;
        }

        if(valueKind == JsonValueKind.Object)
        {
            var obj = node.AsObject();
            foreach(var kvp in obj)
            {
                result.AddRange(ExtractAllJsonPath($"{key}.{kvp.Key}", kvp.Value));
            }

            return result;
        }

        result.Add(key);
        return result;
    }

    private StandaloneEditorConstructionOptions EditorConstructionOptions(StandaloneCodeEditor editor)
    {
        return new StandaloneEditorConstructionOptions
        {
            RenderLineHighlight = "none",
            GlyphMargin = false,
            LineDecorationsWidth = 0,
            Folding = false,
            FixedOverflowWidgets = true,
            AutomaticLayout = true,
            OverviewRulerLanes = 0,
            OverviewRulerBorder = false,
            WordWrap = "false",
            LineNumbers = "false",
            HideCursorInOverviewRuler = true,
            Contextmenu = false,
            RoundedSelection = false,
            Language = "javascript",
            WordBasedSuggestions = false,
            LineNumbersMinChars = 0,
            ScrollBeyondLastColumn = 0,
            Find = new EditorFindOptions
            {
                AddExtraSpaceOnTop = false,
                AutoFindInSelection = false,
                SeedSearchStringFromSelection = "never"
            },
            Minimap = new EditorMinimapOptions
            {
                Enabled = false
            },
            Scrollbar = new EditorScrollbarOptions
            {
                Horizontal = "hidden",
                Vertical = "hidden",
                AlwaysConsumeMouseWheel = false
            },
            Value = ""
        };
    }
}
